import re

from django import http
from django.conf import settings
from django.contrib.auth import login
from django.shortcuts import render, redirect

from QQLoginTool.QQtool import OAuthQQ
# Create your views here.
from django.urls import reverse
from django.views import View
from django_redis import get_redis_connection
from pymysql import DatabaseError

from carts.utils import merge_cart_cookie_to_redis
from meiduo_mall.utils.response_code import RETCODE
from users.models import User
from .utils import generate_access_token, check_access_token
import logging

from oauth.models import OAuthQQUser

logger = logging.getLogger('django')

class QQUserView(View):
    '''用户扫码登录的回调处理'''

    def get(self,request):
        """Oauth2.0认证"""
        # 接收Authorization Code
        code = request.GET.get('code')
        if not code:
            return http.HttpResponseForbidden('缺少code')

        # 创建工具对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)

        try:
            # 携带 code 向 QQ服务器 请求 access_token
            access_token = oauth.get_access_token(code)

            # 携带 access_token 向 QQ服务器 请求 openid
            openid = oauth.get_open_id(access_token)

        except Exception as e:

            # 如果上面获取openid失败,则验证失败
            logger.error(e)

            return http.HttpResponseServerError('OAuth2.0认证失败')

         # 判断该openid在美多商城中是否绑定过用户
        try:
            oauth_user = OAuthQQUser.objects.get(openid=openid)

        except OAuthQQUser.DoesNotExist:
            # 说明没有绑定过用户

            access_token = generate_access_token(openid)

            context = {'access_token':access_token}

            return render(request,'oauth_callback.html',context)
        else:
            # 说明绑定过用户

            # 根据外键,获取qq用户
            qq_user = oauth_user.user

            # 保持登录状态
            login(request, qq_user)

            # 重定向到首页
            response = redirect(reverse('contents:index'))

            response.set_cookie('username', qq_user.username,max_age=3600 * 24 * 15)

            # 合并购物车
            response = merge_cart_cookie_to_redis(request=request, user=qq_user, response=response)
            return response

    def post(self,request):
        '''绑定用户'''


        # 1.获取数据
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        sms_code_client = request.POST.get('sms_code')
        access_token = request.POST.get('access_token')


        # 2.检查数据
        if not all([mobile, password, sms_code_client, access_token]):
            return http.HttpResponseForbidden('缺少必传参数')

        # 检查手机号
        if not re.match(r'^1[3-9]\d{9}$',mobile):
            return http.HttpResponseForbidden('请输入正确的手机号')

        # 检查密码
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('请输入8-20位密码')

        # 连接redis数据库
        redis_conn = get_redis_connection('verify_code')

        # 从数据库取出数据
        sms_code_server = redis_conn.get('sms_code_%s' % mobile)

        # 验证手机号是否存在
        if sms_code_server is None:

            return render(request,'oauth_callback.html',{'sms_code_errmsg':'无效的手机号'})

        if sms_code_client != sms_code_server.decode():

            return render(request,'oauth_callback.html',{'sms_code_errmsg':'短信验证码错误'})


        # 验证access_token
        openid = check_access_token(access_token)

        if not openid:
            return render(request,'oauth_callback.html',{'openid_errmsg':'无效的openid'})

        # 保存数据
        try:
            user = User.objects.get(mobile=mobile)
        except:
            # 没有用户创建用户
            user = User.objects.create_user(username=mobile,password=password,mobile=mobile)
        else:
            # 检查密码
            if not user.check_password(password):
                return render(request, 'oauth_callback.html', {'account_errmsg': '用户名或密码错误'})


        # 5.将用户绑定openid
        try:
            OAuthQQUser.objects.create(openid=openid,user=user)
        except DatabaseError:
            return render(request, 'oauth_callback.html', {'qq_login_errmsg': 'QQ登录失败'})

        # 6.保持登录状态
        login(request,user)

        # 7.响应绑定结果
        next = request.GET.get('state')
        response = redirect(next)


        # 8.写入cookie

        response.set_cookie('username',user.username,max_age=3600 * 24 *15)

        # 合并购物车
        response = merge_cart_cookie_to_redis(request=request, user=user, response=response)
        return response


class QQURLView(View):
    '''
    提供QQ登录网址
    '''

    def get(self,request):
        '''
        QQ登录
        :param request: 请求
        :return:
        '''

        # 无论从那个页面请求,返回这个界面
        next = request.GET.get('next')

        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI,
                        state=next)

        # 调用对象获得qq登录方法
        login_url = oauth.get_qq_url()

        # 返回登录

        return http.JsonResponse({'code':RETCODE.OK,
                                  'errmsg':'ok',
                                  'login_url':login_url})
